package in.muton.edushare.pages.curricula;

import in.muton.edushare.EduShareSession;
import in.muton.edushare.auth.roles.DeptRoleCheck;
import in.muton.edushare.pages.EduShareBasePage;
import in.muton.edushare.pages.deptpages.DeptAcadProgs;
import in.muton.edushare.pages.univ.UnivAcadProgs;
import in.muton.edushare.url.EduShareURLPanel;
import in.muton.edushare.wicket.models.CayenneList;
import in.muton.edushare.wicket.models.CayenneModel;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.wicket.MarkupContainer;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.CSSPackageResource;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.markup.repeater.data.GridView;
import org.apache.wicket.markup.repeater.data.IDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.util.ListModel;

import com.edushare.common.dao.CurriculumDAO;
import com.edushare.common.dao.DepartmentsDAO;
import com.edushare.common.dao.academics.grades.CreditManager;
import com.edushare.common.exceptions.EduShareRuntimeException;
import com.edushare.common.util.StringUtil;
import com.edushare.common.vo.Courses;
import com.edushare.common.vo.Curricula;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Universities;

public class CurriculaSummary extends EduShareBasePage {

	public CurriculaSummary(PageParameters params) {
		init(params);
		add(new Label("currName", currModel.getObject().getCurriculaName()));
		add(new Label("currName2", currModel.getObject().getCurriculaName()));
		add(new EduShareURLPanel("ownerLink", new CayenneModel<Universities>(
				currModel.getObject().getUniversity())));
		add(new EduShareURLPanel("ownerDept", new CayenneModel<Departments>(
				currModel.getObject().getDepartment())));
		add(new Label("semNo", currModel.getObject().getTotalSemester()
				.toString()));
		add(new MultiLineLabel("courseDesc", currModel.getObject()
				.getCurriculaDesc()));
		CreditManager cm = new CreditManager(currModel.getObject(), getSessionORMInterface());
		boolean minMax = cm.getMaxTotalCredits()!=cm.getMinTotalCredits();
		
		WebMarkupContainer wmc = new WebMarkupContainer("credits");
		add(wmc.setVisible(!minMax));
		wmc.add(new Label("credits", cm.getMinTotalCredits()+""));
		
		wmc = new WebMarkupContainer("minCredits");
		add(wmc);
		add(wmc.setVisible(minMax));
		wmc.add(new Label("credits", cm.getMinTotalCredits()+""));
		
		wmc = new WebMarkupContainer("maxCredits");
		add(wmc);
		add(wmc.setVisible(minMax));
		wmc.add(new Label("credits", cm.getMaxTotalCredits()+""));
		

		Departments dept = currModel.getObject().getDepartment();
		DeptRoleCheck drc = new DeptRoleCheck(dept, getLoggedInUser());
		final boolean editVisible = (drc.isPrimaryAdmin() || drc.isUnivAdmin());

		Form<Void> f = new Form<Void>("dummyForm");
		f.add(new Button("finished") {
			@Override
			public void onSubmit() {
				setRespPage();
			}

			private static final long serialVersionUID = 8771300363119934572L;
		});
		add(f);

		add(new ListView<Integer>("semesterRepeatingView", getSemNum()) {
			@Override
			protected void populateItem(ListItem<Integer> arg0) {
				int semNum = arg0.getModelObject();
				CreditManager manager = new CreditManager(
						currModel.getObject(), getSessionORMInterface());
				boolean multipleCredits = manager.getMaxCreditsForSem(semNum) != manager
						.getMinCreditsForSem(semNum);
				arg0.add(new Label("semNo", "" + (semNum + 1)));
				arg0.add(new EditLink("editProgramLink", arg0.getModelObject())
						.setVisible(editVisible));

				arg0.add(new Label("totalCourseCredits", "Semester credits : "
						+ manager.getMinCreditsForSem(semNum))
						.setVisible(!multipleCredits));
				arg0.add(new Label("minCourseCredits",
						"Semester minimum credits : "
								+ manager.getMinCreditsForSem(semNum))
						.setVisible(multipleCredits));
				arg0.add(new Label("maxCourseCredits",
						"Semester maximum credits : "
								+ manager.getMaxCreditsForSem(semNum))
						.setVisible(multipleCredits));

				GridView<IModel<Courses>> gv;
				gv = new GridView<IModel<Courses>>("rows",
						new MandatoryCourseDataProvider(currModel.getObject(),
								arg0.getModelObject())) {
					private static final long serialVersionUID = -306894257620091266L;

					@Override
					protected void populateEmptyItem(Item<IModel<Courses>> item) {
						item.add(new EmptyPanel("courseLink"));
						item.add(new Label("credit", ""));
					}

					@Override
					protected void populateItem(Item<IModel<Courses>> item) {
						item.add(new EduShareURLPanel("courseLink", item
								.getModelObject()));
						item.add(new Label("credit", "("
								+ item.getModelObject().getObject()
										.getBriefDescString()+")"));
					}
				};
				gv.setColumns(2);
				arg0.add(gv);
				arg0.add(getSemesterTableFragment(arg0, currModel.getObject(),
						arg0.getModelObject()));
			}

			private static final long serialVersionUID = -9013124310719338037L;
		});
	}

	private void setRespPage() {
		PageParameters params = new PageParameters();
		if (deptModel != null) {
			params.add("0", deptModel.getObject().getDeptName());
			params.add("1", deptModel.getObject().getDepartmentId().toString());
			setResponsePage(DeptAcadProgs.class, params);
		} else {
			params.put("0", currModel.getObject().getUniversity()
					.getUniqueName());
			setResponsePage(UnivAcadProgs.class, params);
		}
	}

	private Fragment getSemesterTableFragment(MarkupContainer container,
			Curricula curr, int semNo) {
		Fragment f = new Fragment("optionalCoursesRepeatingView",
				"optionalCoursesFragment", container, new Model<Courses>());
		WebMarkupContainer wmcOpt = new WebMarkupContainer("optString");
		f.add(wmcOpt);
		int slots = new CurriculumDAO(getSessionORMInterface())
				.getOptionalCourses(curr, semNo).size();
		if (slots == 0)
			wmcOpt.setVisible(false);

		GridView<List<IModel<Courses>>> gv;
		f.add(gv = new GridView<List<IModel<Courses>>>("rows",
				new OptionalTableDataProvider(curr, semNo)) {
			private static final long serialVersionUID = -3714636982234231517L;

			@Override
			protected void populateEmptyItem(Item<List<IModel<Courses>>> item) {
				WebMarkupContainer wmc = new WebMarkupContainer("courseList");
				wmc.setVisible(false);
				item.add(wmc);
				wmc.add(new EmptyPanel("course"));
				wmc.add(new EmptyPanel("credits"));
				item.add(new Label("slotNo", ""));
			}

			@Override
			protected void populateItem(Item<List<IModel<Courses>>> item) {
				item.add(new Label("slotNo", "Choices for elective "
						+ (item.getIndex() + 1)));
				RepeatingView rv = new RepeatingView("courseList");
				List<IModel<Courses>> lc = item.getModelObject();
				item.add(rv);
				for (IModel<Courses> c : lc) {
					WebMarkupContainer wmc = new WebMarkupContainer(rv
							.newChildId());
					rv.add(wmc);
					wmc.add(new EduShareURLPanel("course", c));
					wmc.add(new Label("credits", "("
							+ c.getObject().getBriefDescString()+")"));
				}
			}
		});
		gv.setColumns(2);
		return f;
	}

	public class OptionalTableDataProvider implements
			IDataProvider<List<IModel<Courses>>> {
		private static final long serialVersionUID = 7748889685786539491L;
		private List<List<IModel<Courses>>> slotCourseList = new ArrayList<List<IModel<Courses>>>();

		public OptionalTableDataProvider(Curricula curr, int semNo) {
			CurriculumDAO cDao = new CurriculumDAO(getSessionORMInterface());
			List<List<Courses>> courseSuperList = cDao.getOptionalCourses(curr,
					semNo);
			int slots = courseSuperList.size();

			for (int i = 0; i < slots; i++) {
				List<Courses> tempList = courseSuperList.get(i);
				List<IModel<Courses>> tempModelList = new ArrayList<IModel<Courses>>();
				for (Courses c : tempList) {
					tempModelList.add(new CayenneModel<Courses>(c));
				}
				slotCourseList.add(tempModelList);
			}
		}

		public Iterator<List<IModel<Courses>>> iterator(int first, int count) {
			List<List<IModel<Courses>>> sublist = slotCourseList.subList(first,
					first + count);
			return sublist.iterator();
		}

		public IModel<List<IModel<Courses>>> model(List<IModel<Courses>> object) {
			return new ListModel<IModel<Courses>>(object);
		}

		public int size() {
			return slotCourseList.size();
		}

		public void detach() {
		}
	}

	private List<Integer> getSemNum() {
		List<Integer> intList = new ArrayList<Integer>();
		for (int i = 0; i < currModel.getObject().getTotalSemester(); i++) {
			intList.add(i);
		}
		return intList;
	}

	private void init(PageParameters params) {
		String currId = params.getString("0");
		CurriculumDAO cDAO = new CurriculumDAO(getSessionORMInterface());
		if (StringUtil.isValid(currId)) {
			Curricula curr = cDAO.getCurriculaById(Integer.parseInt(currId));
			if (curr == null)
				throw new EduShareRuntimeException("Unable to find curricula");
			currModel = new CayenneModel<Curricula>(curr);
		} else {
			throw new EduShareRuntimeException("Unable to find curricula");
		}
		String deptId = params.getString("1");
		DepartmentsDAO dDAO = new DepartmentsDAO(getSessionORMInterface());
		if (StringUtil.isValid(deptId)) {
			Departments dept = dDAO.getDepartmentByPk(Integer.parseInt(deptId));
			if (dept != null) {
				deptModel = new CayenneModel<Departments>(dept);
			}
		} else {
			deptModel = new CayenneModel<Departments>(currModel.getObject()
					.getDepartment());
		}
		add(CSSPackageResource.getHeaderContribution(CurriculaEditor.class,
				"curricula.css"));
	}

	@Override
	public String getPageTitle() {
		return getLoggedInUser().getCompleteUserName() + " | "
				+ currModel.getObject().getCurriculaName()
				+ " | Summary | Edushare";
	}

	@Override
	public String getUserRole() {
		return "";
	}

	private class EditLink extends Link<Void> {
		private static final long serialVersionUID = -7665521874433013123L;

		public EditLink(String id, int sem) {
			super(id);
			targetSem = sem;
		}

		@Override
		public void onClick() {
			PageParameters params = new PageParameters();
			params.put("0", currModel.getObject().getCurriculaId().toString());
			params.put("1", Integer.toString(targetSem));
			WebPage page = new CurriculaEditor(params);
			setResponsePage(page);
		}

		private int targetSem;
	}

	public class MandatoryCourseDataProvider implements
			IDataProvider<IModel<Courses>> {
		private static final long serialVersionUID = -8075057478356881404L;
		List<IModel<Courses>> manCoursesList = null;

		public MandatoryCourseDataProvider(Curricula curr, int semNo) {
			CurriculumDAO cDao = new CurriculumDAO(EduShareSession.get()
					.getSessionORMInterface());
			CayenneList<Courses> courseList = new CayenneList<Courses>(cDao
					.getMandatoryCourses(curr, semNo));
			manCoursesList = courseList.getObject();
		}

		public Iterator<IModel<Courses>> iterator(int first, int count) {
			List<IModel<Courses>> subList = manCoursesList.subList(first, first
					+ count);
			return subList.iterator();
		}

		public IModel<IModel<Courses>> model(IModel<Courses> object) {
			return new Model<IModel<Courses>>(object);
		}

		public int size() {
			return manCoursesList.size();
		}

		public void detach() {
		}
	}

	private IModel<Departments> deptModel = null;
	private IModel<Curricula> currModel = null;
}
